{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 脱出構文と例外処理、大域脱出\n",
    "\n",
    "# 脱出構文、大域脱出\n",
    "\n",
    "* 処理を途中で抜ける方法\n",
    "    * return文\n",
    "    * ループを抜ける脱出構文\n",
    "    * メソッドを抜ける大域脱出"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 脱出構文\n",
    "\n",
    "* break\n",
    "    * ループそのものを中断\n",
    "* next\n",
    "    * 中断して次に進む\n",
    "    * 他の言語ではcontinueに相当\n",
    "* redo\n",
    "    現在の処理をやり直す"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0\n",
      "1\n",
      "3\n",
      "4\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "5"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "5.times do |i|\n",
    "  next if i == 2\n",
    "  puts i\n",
    "end\n",
    "\n",
    "### 2を表示した後2を無限ループで表示\n",
    "# 5.times do |i|\n",
    "#   redo if i == 2\n",
    "#   puts i\n",
    "# end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 例外処理\n",
    "\n",
    "## rise\n",
    "\n",
    "* 例外を発生させる\n",
    "* 第一引数\n",
    "    * 例外クラス又はそのインスタンス\n",
    "* 第二引数\n",
    "    * メッセージ"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "",
     "output_type": "error",
     "traceback": [
      "\u001b[31mRuntimeError\u001b[0m: ",
      "\u001b[37m(pry):1:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "raise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "ename": "ArgumentError",
     "evalue": "引数が不正です(例外クラス)",
     "output_type": "error",
     "traceback": [
      "\u001b[31mArgumentError\u001b[0m: 引数が不正です(例外クラス)",
      "\u001b[37m(pry):11:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "raise ArgumentError, \"引数が不正です(例外クラス)\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "ename": "ArgumentError",
     "evalue": "引数が不正です(例外クラスのインスタンス)",
     "output_type": "error",
     "traceback": [
      "\u001b[31mArgumentError\u001b[0m: 引数が不正です(例外クラスのインスタンス)",
      "\u001b[37m(pry):12:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "raise ArgumentError.new, \"引数が不正です(例外クラスのインスタンス)\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "ename": "ArgumentError",
     "evalue": "引数が不正です(メッセージを含む例外オブジェクト)",
     "output_type": "error",
     "traceback": [
      "\u001b[31mArgumentError\u001b[0m: 引数が不正です(メッセージを含む例外オブジェクト)",
      "\u001b[37m(pry):24:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "### 例外クラスのコンクラスタでメッセージを指定\n",
    "err = ArgumentError.new(\"引数が不正です(メッセージを含む例外オブジェクト)\")\n",
    "raise err"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "ename": "RuntimeError",
     "evalue": "例外クラスのインスタンスを省略した場合はRuntimeError",
     "output_type": "error",
     "traceback": [
      "\u001b[31mRuntimeError\u001b[0m: 例外クラスのインスタンスを省略した場合はRuntimeError",
      "\u001b[37m(pry):25:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "raise \"例外クラスのインスタンスを省略した場合はRuntimeError\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## 例外が発生しても処理を続行させる\n",
    "\n",
    "* rescure節\n",
    "    * 例外が発生したときに実行される処理を記述\n",
    "* else節\n",
    "    * 例外が発生しなかった時の処理を記述\n",
    "* ensure節\n",
    "    * 例外の発生如何に関わらず実行される"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "rescue節\n",
      "例外が発生すると実行されるrescue節\n",
      "\n",
      "else節\n",
      "例外は発生してない\n",
      "例外は発生していないので実行されるelse節\n",
      "\n",
      "ensure節\n",
      "例外が発生すると実行されるrescue節\n",
      "例外発生の如何に関わらず実行されるensure節\n"
     ]
    }
   ],
   "source": [
    "puts \"rescue節\"\n",
    "begin\n",
    "  1 / 0\n",
    "  puts \"例外の下の処理、実行されない\"\n",
    "rescue\n",
    "  puts \"例外が発生すると実行されるrescue節\"\n",
    "end\n",
    "puts\n",
    "\n",
    "puts \"else節\"\n",
    "begin\n",
    "  1\n",
    "  puts \"例外は発生してない\"\n",
    "rescue\n",
    "  puts \"例外は発生してないのでrescue節は実行されない\"\n",
    "else\n",
    "  puts \"例外は発生していないので実行されるelse節\"\n",
    "end\n",
    "puts\n",
    "\n",
    "puts \"ensure節\"\n",
    "begin\n",
    "  1 / 0\n",
    "  puts \"例外の下の処理、実行されない\"\n",
    "rescue\n",
    "  puts \"例外が発生すると実行されるrescue節\"\n",
    "else\n",
    "  puts \"例外が発生しているので実行されないelse節\"\n",
    "ensure\n",
    "  puts \"例外発生の如何に関わらず実行されるensure節\"\n",
    "end\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## beginを書かかずにrescue節を記述"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "begin無しrescue節\n"
     ]
    }
   ],
   "source": [
    "1 / 0 rescue puts \"begin無しrescue節\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## メソッドの中でrescue節を実行"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "メソッドの中でrescueを実行\n"
     ]
    }
   ],
   "source": [
    "def foo\n",
    "  1 / 0\n",
    "rescue\n",
    "  puts \"メソッドの中でrescueを実行\"\n",
    "end\n",
    "foo"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 例外クラスを指定した捕捉\n",
    "\n",
    "* 例外クラスの捕捉\n",
    "    * 例外クラスを指定せずにrescue節が補足する対象\n",
    "        * StandardErrorとそのサブクラス\n",
    "* 例外クラスの階層\n",
    "* Exception\n",
    "    * ScriptError\n",
    "        * SyntaxError : 文法エラーがあった場合\n",
    "        * <font color=\"red\">文法エラーは例外クラスを指定しないと捕捉されない</font>\n",
    "    * SignalException : 捕捉していないシグナルを受けた場合\n",
    "    * StandardError\n",
    "        * ArgumentError : 引数の数が合わないときや値が正しくないとき\n",
    "        * RuntimeError : 特定の例外クラスに該当しないエラー、もしくは例外クラスを省略してraiseを呼び出した場合\n",
    "        * NameError : 未定義のローカル変数や定数を参照した場合\n",
    "            * NoMethodError : 未定義のメソッドを呼び出した場合\n",
    "        * ZeroDivisionError : 整数に対して整数の0で除算を行った場合"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "例外オブジェクトの取得。backtraceで例外が発生した場所を参照\n",
      "[\"(pry):69:in `/'\", \"(pry):69:in `<main>'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\", \"/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\"]\n"
     ]
    }
   ],
   "source": [
    "puts \"例外オブジェクトの取得。backtraceで例外が発生した場所を参照\"\n",
    "begin\n",
    "  1/0\n",
    "rescue ZeroDivisionError => e\n",
    "  puts e.backtrace\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## $! による最後の例外の取得と再発生"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ZeroDivisionError\n",
      "divided by 0\n"
     ]
    },
    {
     "ename": "ZeroDivisionError",
     "evalue": "divided by 0",
     "output_type": "error",
     "traceback": [
      "\u001b[31mZeroDivisionError\u001b[0m: divided by 0",
      "\u001b[37m(pry):187:in `/'\u001b[0m",
      "\u001b[37m(pry):187:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "begin\n",
    "  1/0\n",
    "rescue ZeroDivisionError => e\n",
    "  puts $!.class\n",
    "  puts $!\n",
    "  raise\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## retry\n",
    "\n",
    "* 例外が発生したらrescue節を全て実行した後、再度beginから処理を実効する"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 57,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "一回目は6/0で例外発生。rescure節でaに3が加えられてretryで再度beginから実行され6/3が計算される\n",
      "0\n",
      "2回目は例外発生せずensure節で計算結果の2が出力される\n",
      "2\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 57,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "a = 0\n",
    "b = 0\n",
    "\n",
    "begin\n",
    "  b = 6/a\n",
    "rescue ZeroDivisionError\n",
    "  puts \"一回目は6/0で例外発生。rescure節でaに3が加えられてretryで再度beginから実行され6/3が計算される\"\n",
    "  puts b\n",
    "  a += 3\n",
    "  retry\n",
    "ensure\n",
    "  puts \"2回目は例外発生せずensure節で計算結果の2が出力される\"\n",
    "  puts b\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## rescue節の実行順\n",
    "\n",
    "* rescue節は一つのbegin節の中にいくらでも書くことができる\n",
    "* 最初にマッチしたものしか実行されない\n",
    "    * <font color=\"red\">マッチする範囲が広くなる順に指定する</font>\n",
    "        * 後でより狭い例外クラスを指定しても役に立たない"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 58,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "begin\n",
    "  1/0\n",
    "rescue\n",
    "  p 1\n",
    "rescue ZeroDivisionError\n",
    "  p 2\n",
    "end"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "# 大域脱出\n",
    "\n",
    "## catch/throw\n",
    "\n",
    "* 正常時であっても処理を抜けたいとき\n",
    "    * 階層の深いループの中で全ての処理が完了した場合など\n",
    "* 例外との対応イメージ\n",
    "    * raise <-> throw\n",
    "    * begin節 <-> catch\n",
    "* 処理の流れ\n",
    "    * throwが実行される\n",
    "    * 同名のラベル(ここでは:exit)が指定されているcatchまで呼び出してスタックをたどる\n",
    "    * 見つかった場合はそのブロック内における後続の処理をスキップする\n",
    "* ラベル\n",
    "    * シンボルや文字列を指定できる\n",
    "* ラベルが見つからない場合はNameErrorが発生"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 88,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "catchにおいてthrowの設定されているfooメソッド(ラベルは:exit)以降は実行されない\n",
      "throwありメソッド\n",
      "1\n",
      "===\n",
      "barメソッドにthrowが設定されていないのでcatch内は全て実行される\n",
      "throw無しメソッド\n",
      "catch内。実行される\n",
      "2\n",
      "===\n",
      "ラベルが一致しない場合はエラーになる\n",
      "throwとcatchのラベルが一致してない\n"
     ]
    },
    {
     "ename": "UncaughtThrowError",
     "evalue": "uncaught throw :hoge",
     "output_type": "error",
     "traceback": [
      "\u001b[31mUncaughtThrowError\u001b[0m: uncaught throw :hoge",
      "\u001b[37m(pry):1217:in `throw'\u001b[0m",
      "\u001b[37m(pry):1217:in `baz'\u001b[0m",
      "\u001b[37m(pry):1221:in `block in <main>'\u001b[0m",
      "\u001b[37m(pry):1220:in `catch'\u001b[0m",
      "\u001b[37m(pry):1220:in `<main>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:355:in `evaluate_ruby'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:323:in `handle_line'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:243:in `block (2 levels) in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:242:in `block in eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `catch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/pry-0.10.4/lib/pry/pry_instance.rb:241:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:66:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/backend.rb:12:in `eval'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:87:in `execute_request'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:47:in `dispatch'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/kernel.rb:37:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:70:in `run_kernel'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/lib/iruby/command.rb:34:in `run'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/gems/iruby-0.3/bin/iruby:5:in `<top (required)>'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `load'\u001b[0m",
      "\u001b[37m/Users/ftakao2007/work/jupyter/vendor/bundle/ruby/2.3.0/bin/iruby:23:in `<main>'\u001b[0m"
     ]
    }
   ],
   "source": [
    "puts \"catchにおいてthrowの設定されているfooメソッド(ラベルは:exit)以降は実行されない\"\n",
    "def foo\n",
    "  puts \"throwありメソッド\"\n",
    "  throw :exit\n",
    "end\n",
    "\n",
    "catch(:exit) {\n",
    "  foo\n",
    "  puts \"catch内。実行されない\"\n",
    "}\n",
    "puts \"1\"\n",
    "puts \"===\"  \n",
    "\n",
    "puts \"barメソッドにthrowが設定されていないのでcatch内は全て実行される\"\n",
    "def bar\n",
    "  puts \"throw無しメソッド\"\n",
    "end\n",
    "\n",
    "catch(:exit2) {\n",
    "  bar\n",
    "  puts \"catch内。実行される\"\n",
    "}\n",
    "puts \"2\"\n",
    "puts \"===\"\n",
    "\n",
    "puts \"ラベルが一致しない場合はエラーになる\"\n",
    "def baz\n",
    "  puts \"throwとcatchのラベルが一致してない\"\n",
    "  throw :hoge\n",
    "end\n",
    "\n",
    "catch(:exit3) {\n",
    "  baz\n",
    "  puts \"catch内。実行される\"\n",
    "}\n",
    "puts \"3\"\n",
    "  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "## catchの戻り値をthrowに渡して実行\n",
    "\n",
    "* throwに渡した値はcatchの戻り値とすることができる"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "メソッドの中にcatchとthrowを書く\n",
      "100\n",
      "今までの例の書き方で実行\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "200"
      ]
     },
     "execution_count": 95,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "puts \"メソッドの中にcatchとthrowを書く\"\n",
    "def bar\n",
    "  catch(:calc) do\n",
    "    throw :calc, 100\n",
    "  end\n",
    "end\n",
    "puts bar\n",
    "\n",
    "puts \"今までの例の書き方で実行\"\n",
    "def foo\n",
    "  throw :exit, 200\n",
    "end\n",
    "\n",
    "catch(:exit) {\n",
    "  puts foo\n",
    "}"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Ruby 2.3.1",
   "language": "ruby",
   "name": "ruby"
  },
  "language_info": {
   "file_extension": ".rb",
   "mimetype": "application/x-ruby",
   "name": "ruby",
   "version": "2.3.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
